package com.huilian.netty.consumer;

import com.alibaba.fastjson.JSON;
import com.huilian.iotbox.data.common.RedisKey;
import com.huilian.iotbox.data.enums.MessageLogResultEnum;
import com.huilian.iotbox.data.po.MessageLog;
import com.huilian.iotbox.data.producer.MessageLogRabbit;
import com.huilian.iotbox.data.service.BlueToothPubService;
import com.huilian.iotbox.data.service.ErrorLogCommonService;
import com.huilian.iotbox.data.vo.*;
import com.huilian.netty.constant.CIMConstant;
import com.huilian.netty.handler.CIMNioSocketAcceptor;
import com.huilian.netty.model.CIMSession;
import com.huilian.netty.model.SocketMessage;
import com.huilian.netty.repository.SessionRepository;
import com.huilian.netty.service.DeviceService;
import com.rabbitmq.client.Channel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.io.Serializable;
import java.util.*;

@Component
@Slf4j
public class RabbitReceiver {
    @Autowired
    private DeviceService deviceService;
    @Autowired
    private ErrorLogCommonService errorLogCommonService;
    @Autowired
    private RedisTemplate<String, Serializable> redisCacheTemplate;
    @Autowired
    private MessageLogRabbit messageLogRabbit;
    @Autowired
    private SessionRepository sessionRepository;



    /**
     * 拿到电机检测结果发webSock到前端
     *
     * @return void
     * @Author xuxiaoning
     * @Date 2024/3/15
     */
    @RabbitListener(bindings = @QueueBinding(value = @Queue(value = "${spring.rabbitmq.listener.iotBoxMotorTestingResult" +
            ".queue.name}",
            durable = "${spring.rabbitmq.listener.iotBoxMotorTestingResult.queue.durable}"),
            exchange = @Exchange(value = "${spring.rabbitmq.listener.iotBoxMotorTestingResult.exchange.name}",
                    durable = "${spring.rabbitmq.listener.iotBoxMotorTestingResult.exchange.durable}",
                    type = "${spring.rabbitmq.listener.iotBoxMotorTestingResult.exchange.type}"),
            ignoreDeclarationExceptions = "${spring.rabbitmq.listener.iotBoxMotorTestingResult.exchange.ignoreDeclarationExceptions}",
            key = "${spring.rabbitmq.listener.iotBoxMotorTestingResult.key}"))
    @RabbitHandler
    public void motorTestingResult(@Payload DeviceVo deviceVo, Channel channel, @Headers Map<String, Object> headers) throws IOException {
        try {
            log.info("从队列【电机检测结果通过webSocket同步到前端】接收到消息:{}", JSON.toJSONString(deviceVo));
            String key = String.format(RedisKey.MQTT_MOTOR_TESTING_SOCKET_ID, deviceVo.getDeviceNo(), deviceVo.getHierarchy(), deviceVo.getFreightLane());
            /**
             * socketId 组成
             * 商家端 merchant_ + userId
             * 用户端 client_ + memberId
             */
            String socketId = (String) redisCacheTemplate.opsForValue().get(key);
            log.info("socketId:{}", socketId);
            log.info("deviceNo:{}", deviceVo.getDeviceNo());
            if (StringUtils.isEmpty(socketId)) {
                log.warn("缓存socketId为空,key:" + key);
                return;
            }
            SocketMessage body = new SocketMessage();
            body.setType(CIMConstant.MessageType.CLIENT_MESSAGE);
            body.setMotorStatus(deviceVo.getMotorStatus());
            body.setHierarchy(deviceVo.getHierarchy());
            body.setFreightLane(deviceVo.getFreightLane());
            body.setNumberOfFailures(deviceVo.getNumberOfFailures());
            List<CIMSession> cimSessionList = sessionRepository.get(socketId);
            for (CIMSession c:cimSessionList) {
                TextWebSocketFrame textWebSocketFrame = new TextWebSocketFrame(JSON.toJSONString(body));
                c.write(textWebSocketFrame);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("获取到电机检测结果通过webSocket同步到前端处理失败{}", e.toString());
            errorLogCommonService.writerInfoException("获取到电机检测结结果通过webSocket同步到前端处理失败", deviceVo, e);
        } finally {
            Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
            //手工ACK
            channel.basicAck(deliveryTag, true);
        }
    }



    /**
     *  将协议通过netty发送给小程序-小程序启动蓝牙模块
     */
    @RabbitListener(bindings = @QueueBinding(value = @Queue(value = "${spring.rabbitmq.listener.iotBoxBlueToothPubMessage" +
            ".queue.name}",
            durable = "${spring.rabbitmq.listener.iotBoxBlueToothPubMessage.queue.durable}"),
            exchange = @Exchange(value = "${spring.rabbitmq.listener.iotBoxBlueToothPubMessage.exchange.name}",
                    durable = "${spring.rabbitmq.listener.iotBoxBlueToothPubMessage.exchange.durable}",
                    type = "${spring.rabbitmq.listener.iotBoxBlueToothPubMessage.exchange.type}"),
            ignoreDeclarationExceptions = "${spring.rabbitmq.listener.iotBoxBlueToothPubMessage.exchange.ignoreDeclarationExceptions}",
            key = "${spring.rabbitmq.listener.iotBoxBlueToothPubMessage.key}"))
    @RabbitHandler
    public void blueToothPubMessage(@Payload String json, Channel channel, @Headers Map<String, Object> headers) throws IOException {
        MessageLog messageLog = JSON.parseObject(json, MessageLog.class);
        try {
            log.info("blueToot send:" + json);

            if (StringUtils.isEmpty(messageLog.getContent())){
                errorLogCommonService.writerInfoErrorLog("webSock发送内容为空", messageLog);
                return;
            }
            SocketMessage body = new SocketMessage();
            body.setType(CIMConstant.MessageType.CLIENT_MESSAGE);
            body.setCommand(messageLog.getContent());
            List<CIMSession> cimSessionList = sessionRepository.get(messageLog.getUsername());
            for(int i= 0;i<cimSessionList.size();i++){
                log.info("cimSessionList.get(i):{}",cimSessionList.get(i).getNid());
                TextWebSocketFrame textWebSocketFrame = new TextWebSocketFrame(JSON.toJSONString(body));
                cimSessionList.get(i).write(textWebSocketFrame);
            }
        } catch (Exception e) {
            e.printStackTrace();
            messageLog.setResult(MessageLogResultEnum.FAIL.getCode());
            log.error("webSock发送消息不成功：{}", e.getMessage());
            errorLogCommonService.writerInfoException("webSock发送消息不成功", messageLog, e);
        } finally {
            Long deliveryTag = (Long) headers.get(AmqpHeaders.DELIVERY_TAG);
            //手工ACK
            channel.basicAck(deliveryTag, true);
            messageLog.setResult(MessageLogResultEnum.SUCCESS.getCode());
            messageLogRabbit.sendMessageLog(messageLog);
        }
    }
}
